#!/bin/sh
#
# This is SORT OF LIKE an X session, but not quite.  You get a command as the
# first argument (it could be multiple words, so run it with "eval").  As a
# special case, the command can be:
#  default - Run the appropriate Xclients startup (see the code below)
#  custom - Run ~/.xsession and if that's not available run 'default'
#
# (Note that other arguments could also follow, but only the command one is
# right now relevant and supported)
#
# The output is ALREADY redirected to .xsession-errors in GDM.  This way
# .xsession-errors actually gets more output such as if the PreSession script
# is failing.  This also prevents DoS attacks if some app in the users session
# can be prodded to dump lots of stuff on the stdout/stderr.  We wish to be
# robust don't we?  In case you wish to use an existing script for other DM's,
# you can just not redirect when GDMSESSION is set.  GDMSESSION will always
# be set from gdm.
#
# Also note that this is not run as a login shell, this is just executed.
# This is why we source the profile files below.
#
# based on:
# $XConsortium: Xsession /main/10 1995/12/18 18:21:28 gildea $

command="$@"

# this will go into the .xsession-errors along with all other echo's
# good for debugging where things went wrong
echo "$0: Beginning session setup..."

# First read /etc/profile and .profile
test -f /etc/profile && . /etc/profile
test -f "$HOME/.profile" && . "$HOME/.profile"
# Second read /etc/xprofile and .xprofile for X specific setup
test -f /etc/xprofile && . /etc/xprofile
test -f "$HOME/.xprofile" && . "$HOME/.xprofile"

# Translation stuff
if [ -x "/usr/lib/gdm/gdmtranslate" ] ; then
  gdmtranslate="/usr/lib/gdm/gdmtranslate"
else
  gdmtranslate=
fi

# Note that this should only go to zenity dialogs which always expect utf8
gettextfunc () {
  if [ "x$gdmtranslate" != "x" ] ; then
    "$gdmtranslate" --utf8 "$1"
  else
    echo "$1"
  fi
}

OLD_IFS=$IFS

gdmwhich () {
  COMMAND="$1"
  OUTPUT=
  IFS=:
  for dir in $PATH
  do
    if test -x "$dir/$COMMAND" ; then
      if test "x$OUTPUT" = "x" ; then
        OUTPUT="$dir/$COMMAND"
      fi
    fi
  done
  IFS=$OLD_IFS 
  echo "$OUTPUT"
}

zenity=`gdmwhich zenity`

# Note: ~/.xsession-errors is now done in the daemon so that it
# works for ALL sessions (except ones named 'Failsafe')

# clean up after xbanner
freetemp=`gdmwhich freetemp`
if [ -n "$freetemp" ] ; then
	"$freetemp"
fi

userresources="$HOME/.Xresources"
usermodmap="$HOME/.Xmodmap"
userxkbmap="$HOME/.Xkbmap"

sysresources=/etc/X11/Xresources 
sysmodmap=/etc/X11/Xmodmap 
sysxkbmap=/etc/X11/Xkbmap

rh6sysresources=/etc/X11/xinit/Xresources 
rh6sysmodmap=/etc/X11/xinit/Xmodmap 

# merge in defaults
if [ -f "$rh6sysresources" ]; then
    xrdb -nocpp -merge "$rh6sysresources"
fi

if [ -f "$sysresources" ]; then
    xrdb -nocpp -merge "$sysresources"
fi

if [ -f "$userresources" ]; then
    xrdb -nocpp -merge "$userresources"
fi

# merge in keymaps
if [ -f "$sysxkbmap" ]; then
    setxkbmap `cat "$sysxkbmap"`
    XKB_IN_USE=yes
fi

if [ -f "$userxkbmap" ]; then
    setxkbmap `cat "$userxkbmap"`
    XKB_IN_USE=yes
fi

#
# Eeek, this seems like too much magic here
#
if [ -z "$XKB_IN_USE" -a ! -L /etc/X11/X ]; then
    if grep '^exec.*/Xsun' /etc/X11/X > /dev/null 2>&1 && [ -f /etc/X11/XF86Config ]; then
       xkbsymbols=`sed -n -e 's/^[     ]*XkbSymbols[   ]*"\(.*\)".*$/\1/p' /etc/X11/XF86Config`
       if [ -n "$xkbsymbols" ]; then
           setxkbmap -symbols "$xkbsymbols"
           XKB_IN_USE=yes
       fi
    fi
fi

# xkb and xmodmap don't play nice together
if [ -z "$XKB_IN_USE" ]; then
    if [ -f "$rh6sysmodmap" ]; then
       xmodmap "$rh6sysmodmap"
    fi

    if [ -f "$sysmodmap" ]; then
       xmodmap "$sysmodmap"
    fi

    if [ -f "$usermodmap" ]; then
       xmodmap "$usermodmap"
    fi
fi

unset XKB_IN_USE

language_environment_update() {
    langcode=${gdm_selected%%[_@]*}
    if [ -z "$langlist" ] || [ $gdm_selected != ${langlist%%:*} ]; then
        # make the first value in the LANGUAGE priority list correspond
        # with the language selected in the GDM greeter
        if [ -n "$langlist" -a $langcode != 'en' ]; then
            if expr $langlist : ".*:$gdm_selected:" > /dev/null ; then
                langlist=$( echo $langlist | sed -r "s/(.+:)($gdm_selected:)/\2\1/" )
            else
                langlist=$gdm_selected:$langlist
            fi
        else
            # build list with 'en' as the last element
            # no other languages if English was selected
            langlist=$gdm_selected
            [ $langlist != 'en' ] && langlist=$langlist:en
        fi
    fi

    # set LC_MESSAGES for applications that don't recognize LANGUAGE
    #
    lcmess=
    locales=
    # skip locales for other languages
    for loc in $( locale -a | grep -F .utf8 ); do
        if [ $langcode = ${loc%%[._@]*} ]; then
            loc=${loc%.*}${loc#*.utf8}
            locales=$locales" $loc"
        fi
    done
    # exact match
    for loc in $locales; do
        if [ $gdm_selected = $loc ]; then
            lcmess=$( echo $loc | sed -r 's/([^@]+)/\1.UTF-8/' )
            break
        fi
    done
    if [ -z "$lcmess" -a $gdm_selected = ${gdm_selected%_*} ]; then
        # try the "main" country code if any
        main_countries=/usr/share/language-selector/data/main-countries
        test -f $main_countries && {
            main_country=
            while read line; do
                if [ "${line%%[[:space:]]*}" = $langcode ]; then
                    main_country=${line##*[[:space:]]}
                    if [ $langcode != ${gdm_selected#*@} ]; then
                        main_country=$main_country@${gdm_selected#*@}
                    fi
                    break
                fi
            done < $main_countries
            if [ -n "$main_country" ]; then
                for loc in $locales; do
                    if [ $main_country = $loc ]; then
                        lcmess=$( echo $loc | sed -r 's/([^@]+)/\1.UTF-8/' )
                        break
                    fi
                done
            fi
        }
        # try out fitting locale with any country code
        if [ -z "$lcmess" ]; then
            for loc in $locales; do
                if [ $langcode = ${loc%%[_@]*} ]; then
                    lcmess=$( echo $loc | sed -r 's/([^@]+)/\1.UTF-8/' )
                    break
                fi
            done
        fi
    fi

    dmrc_update() {
        key=$1; value=$2
        if [ "$( grep -F $key $dmrc )" ]; then
            sed -i "s/$key.*/$key=$value/" $dmrc
        else
            echo "$key=$value" >> $dmrc
        fi
    }
    dmrc_update 'Langlist' $langlist
    dmrc_update 'LCMess' $lcmess
}

# read /var/cache/gdm/$USER/dmrc and set LANGUAGE and LC_MESSAGES
if [ -n "$GDM_LANG" -a "${DESKTOP_SESSION#*guest}" != '-restricted' ]; then
    if [ $GDM_LANG != ${GDM_LANG%.utf8*} ]; then
        gdm_selected=${GDM_LANG%.*}${GDM_LANG#*.utf8}
    elif [ $GDM_LANG != ${GDM_LANG%.UTF-8*} ]; then
        gdm_selected=${GDM_LANG%.*}${GDM_LANG#*.UTF-8}
    else
        gdm_selected=$GDM_LANG
    fi
    dmrc=/var/cache/gdm/$USER/dmrc
    test -f "$dmrc" || {
        echo "\n[Desktop]\nLanguage=$gdm_selected" > $dmrc
    }
    while read line; do
        [ "${line%=*}" = 'Langlist' ] && langlist=${line#*=}
        [ "${line%=*}" = 'LCMess' ] && lcmess=${line#*=}
    done < $dmrc
    if [ -z "$langlist" -a -z "$lcmess" -a -f "$HOME/.xsession-errors.old" ]; then
        # Both fields empty and not $USER's first login ever => we assume that this is
        # $USER's first login since upgrading from a pre 2.32.0-0ubuntu2 GDM version,
        # so we fake $gdm_selected in an attempt to get the language environment right
        # from start and prevent an undesired surprise.
        if [ -n "$LANGUAGE" ]; then
            gdm_selected=${LANGUAGE%%:*}
            if [ "$( grep -F Language $dmrc )" ]; then
                sed -i "s/Language=.*/Language=$gdm_selected/" $dmrc
            else
                echo "Language=$gdm_selected" >> $dmrc
            fi
        fi
    fi
    if [ -z "$langlist" ] || [ $gdm_selected != ${langlist%%:*} ]; then
        # If the user changed language, update the env. values and edit the cache file.
        language_environment_update
    fi
    export LANGUAGE="$langlist"
    if [ $LANG != ${LANG%.utf8*} ]; then
        x_lang=${LANG%.*}.UTF-8${LANG#*.utf8}
    else
        x_lang=${LANG%.*}.utf8${LANG#*.UTF-8}
    fi
    if [ -n "$lcmess" -a $lcmess != $LANG -a $lcmess != $x_lang ]; then
        export LC_MESSAGES="$lcmess"
    else
        # no fitting locale or same as LANG
        unset LC_MESSAGES
    fi
fi

# run all system xinitrc shell scripts.
if [ -d /etc/X11/xinit/xinitrc.d ]; then
    for i in /etc/X11/xinit/xinitrc.d/* ; do
        if [ -x "$i" -a ! -d "$i" ]; then
	    . "$i"
        fi
    done
fi

# run /etc/X11/Xsession.d/
OPTIONFILE=/etc/X11/Xsession.options
USERXSESSION=$HOME/.xsession
USERXSESSIONRC=$HOME/.xsessionrc
ALTUSERXSESSION=$HOME/.Xsession
if [ -d /etc/X11/Xsession.d ]; then
    for i in `ls /etc/X11/Xsession.d/` ; do
        if [ -r "/etc/X11/Xsession.d/$i"  -a -f "/etc/X11/Xsession.d/$i" ] && expr "$i" : '^[[:alnum:]_-]\+$' > /dev/null; then
	    . "/etc/X11/Xsession.d/$i"
        fi
    done
fi

if [ "x$command" = "xcustom" ] ; then
  if [ -x "$HOME/.xsession" ]; then
    command="$HOME/.xsession"
  else
    echo "$0: Cannot find ~/.xsession will try the default session"
    command="default"
  fi
fi

if [ "x$command" = "xdefault" ] ; then
  if [ -x "$HOME/.Xclients" ]; then
    command="$HOME/.Xclients"
  elif [ -x /etc/X11/xinit/Xclients ]; then
    command="/etc/X11/xinit/Xclients"
  elif [ -x /etc/X11/Xclients ]; then
    command="/etc/X11/Xclients"
  else
    if [ -n "$zenity" ] ; then
	disptext=`gettextfunc "System has no Xclients file, so starting a failsafe xterm session.  Windows will have focus only if the mouse pointer is above them.  To get out of this mode type 'exit' in the window."`
      "$zenity" --info --text "$disptext"
    else
      echo "$0: Cannot find Xclients"
    fi
    exec xterm -geometry 80x24+0+0
  fi
fi

# add ssh-agent if found
sshagent="`gdmwhich ssh-agent`"
if [ -n "$sshagent" ] && [ -x "$sshagent" ] && [ -z "$SSH_AUTH_SOCK" ]; then
    command="$sshagent -- $command"
elif [ -z "$sshagent" ] ; then
    echo "$0: ssh-agent not found!"
fi

echo "$0: Setup done, will execute: $command"

eval exec $command

echo "$0: Executing $command failed, will run xterm"

if [ -n "$zenity" ] ; then
	disptext=`gettextfunc "Failed to start the session, so starting a failsafe xterm session.  Windows will have focus only if the mouse pointer is above them.  To get out of this mode type 'exit' in the window."`
	"$zenity" --info --text "$disptext"
fi

exec xterm -geometry 80x24+0+0
